import {
    Attachments,
    Bubble,
    Sender,
    Welcome,
} from '@ant-design/x';
import { createStyles } from 'antd-style';
import React, { useEffect} from 'react';

import {
    CloudUploadOutlined,
    EllipsisOutlined,
    PaperClipOutlined,
    ShareAltOutlined,
} from '@ant-design/icons';
import { message, Badge, Button, type GetProp, Space } from 'antd';
import AgentAvatar from '../../components/AgentAvatar';
import { Markdown } from '@lobehub/ui';

const useStyle = createStyles(({ token, css }) => {
    return {
        layout: css`
        width: 100%;
        min-width: 1000px;
        flex: 1;
        border-radius: ${token.borderRadius}px;
        display: flex;
        background: ${token.colorBgContainer};
        font-family: AlibabaPuHuiTi, ${token.fontFamily}, sans-serif;
  
        .ant-prompts {
          color: ${token.colorText};
        }
      `,
        menu: css`
        background: ${token.colorBgLayout}80;
        width: 280px;
        height: 100%;
        display: flex;
        flex-direction: column;
      `,
        conversations: css`
        padding: 0 12px;
        flex: 1;
        overflow-y: auto;
      `,
        chat: css`
        height: 100%;
        width: 100%;
        max-width: 700px;
        margin: 0 auto;
        box-sizing: border-box;
        display: flex;
        flex-direction: column;
        padding: ${token.paddingLG}px;
        gap: 16px;
        overflow: auto;
        height: calc(100vh - 65px);
      `,
        messages: css`
        flex: 1;
      `,
        placeholder: css`
        padding-top: 32px;
      `,
        sender: css`
        box-shadow: ${token.boxShadow};
      `,
        logo: css`
        display: flex;
        height: 72px;
        align-items: center;
        justify-content: start;
        padding: 0 24px;
        box-sizing: border-box;
  
        img {
          width: 24px;
          height: 24px;
          display: inline-block;
        }
  
        span {
          display: inline-block;
          margin: 0 8px;
          font-weight: bold;
          color: ${token.colorText};
          font-size: 16px;
        }
      `,
        addBtn: css`
        background: #1677ff0f;
        border: 1px solid #1677ff34;
        width: calc(100% - 24px);
        margin: 0 12px 24px 12px;
      `,
    };
});


const roles: GetProp<typeof Bubble.List, 'roles'> = {
    ai: {
        placement: 'start',
        typing: { step: 5, interval: 20 },
        avatar: <AgentAvatar title="AGI" />,
        styles: {
            content: {
                borderRadius: 16,
            },
        },
    },
    local: {
        placement: 'end',
        variant: 'shadow',
    },
};

interface AgentChatProps {
    connection: signalR.HubConnection;
    connectionStatus: 'success' | 'error' | 'warning' | 'info';
    model?: string;
}

const AgentChat = ({
    connection,
    connectionStatus,
    model,
}: AgentChatProps) => {
    // ==================== Style ====================
    const { styles } = useStyle();

    // ==================== State ====================
    const [headerOpen, setHeaderOpen] = React.useState(false);
    const [isGenerating, setIsGenerating] = React.useState(false);

    const [content, setContent] = React.useState('');

    const [attachedFiles, setAttachedFiles] = React.useState<GetProp<typeof Attachments, 'items'>>(
        [],
    );

    const [messages, setMessages] = React.useState<any[]>([]);


    // ==================== Event ====================
    const onSubmit = async (nextContent: string) => {
        if (!nextContent) return;
        try {
            setContent('');
            setIsGenerating(true);

            const newMessage = {
                id: Date.now(),
                message: nextContent,
                status: 'local',
                agentName: 'user',
                avatar: '🤯',
                placement: 'end',
                content: nextContent,
            };

            messages.push(newMessage)

            setMessages([...messages]);

            await connection.invoke("SendAgent", nextContent,model);

        } finally {
            setIsGenerating(false);
        }
    };


    const handleFileChange: GetProp<typeof Attachments, 'onChange'> = (info) =>
        setAttachedFiles(info.fileList);

    // ==================== Nodes ====================
    const placeholderNode = (
        <Space direction="vertical" size={16} className={styles.placeholder}>
            <Welcome
                variant="borderless"
                icon="https://mdn.alipayobjects.com/huamei_iwk9zp/afts/img/A*s5sNRo5LjfQAAAAAAAAAAAAADgCCAQ/fmt.webp"
                title="欢迎使用 AGI"
                description="AGI 是一个基于 AI大模型提供的能力实现自动构建项目，帮你轻松构建一个整体的项目结构。"
                extra={
                    <Space>
                        <Button icon={<ShareAltOutlined />} />
                        <Button icon={<EllipsisOutlined />} />
                    </Space>
                }
            />
        </Space>
    );

    const items: GetProp<typeof Bubble.List, 'items'> = messages.map(({ id, avatar, message, status, agentName,placement }) => ({
        key: id,
        role: status === 'local' ? 'local' : 'ai',
        placement: placement,
        header: agentName,
        avatar: <AgentAvatar
            avatar={avatar}
            clickable />,
        content: <Markdown
            fullFeaturedCodeBlock
            enableImageGallery
            enableMermaid
            enableLatex
            fontSize={12}
            >
            {message ?? "思考中..."}
        </Markdown>,
    }));

    const attachmentsNode = (
        <Badge dot={attachedFiles.length > 0 && !headerOpen}>
            <Button type="text" icon={<PaperClipOutlined />} onClick={() => setHeaderOpen(!headerOpen)} />
        </Badge>
    );

    const senderHeader = (
        <Sender.Header
            title="Attachments"
            open={headerOpen}
            onOpenChange={setHeaderOpen}
            styles={{
                content: {
                    padding: 0,
                },
            }}
        >
            <Attachments
                beforeUpload={() => false}
                items={attachedFiles}
                onChange={handleFileChange}
                placeholder={(type) =>
                    type === 'drop'
                        ? { title: 'Drop file here' }
                        : {
                            icon: <CloudUploadOutlined />,
                            title: 'Upload files',
                            description: 'Click or drag files to this area to upload',
                        }
                }
            />
        </Sender.Header>
    );

    useEffect(() => {
        if (connection) {
            let agent = {
                id: Date.now(),
                message: '',
                status: 'ai',
                agentName: 'AGI',
                agentId: '',
                avatar: '🤖',
                placement: 'start',
            }

            connection.on('AgentProtocol', (value) => {
                if (value.type === 'init') {
                    message.success('初始化Agent成功')
                } else if (value.type === "text") {
                    if (value.result) {
                        if (agent.agentId === value.agentId) {
                            agent.message = value.result;
                            setMessages([...messages])
                        } else {
                            agent = {
                                id: value.agentId,
                                message: value.result,
                                status: 'ai',
                                agentName: value.agentName,
                                agentId: value.agentId,
                                avatar: '🤖',
                                placement: 'start',
                            }
                            messages.push(agent);
                            setMessages([...messages])
                        }
                    }
                }
            });

            // NotifyUserTaskDone 后端需要返回值
            connection.on('NotifyUserTaskDone', (value) => {
                let promise = new Promise((resolve, reject) => {
                    const result = window.prompt(value, '');
                    if (result === null) {
                        reject('');
                    } else {
                        resolve(result);
                    }
                });
                return promise;
            });

        }

        // 取消订阅
        return () => {
            connection.off('AgentProtocol');
            connection.off('NotifyUserTaskDone');
        }
    }, [connection]);

    return (
        <div className={styles.layout}>
            <div className={styles.chat}>
                <Bubble.List
                    items={items.length > 0 ? items : [{ content: placeholderNode, variant: 'borderless' }]}
                    roles={roles}
                    className={styles.messages}
                />
                <Sender
                    value={content}
                    header={senderHeader}
                    onSubmit={onSubmit}
                    onChange={setContent}
                    disabled={connectionStatus !== 'success'}
                    prefix={attachmentsNode}
                    loading={isGenerating}
                    className={styles.sender}
                />
            </div>
        </div>
    );
};

export default AgentChat;